package cn.rulian.tempcode.hello.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.rulian.base.common.service.BaseService;
import cn.rulian.base.common.util.Num;
import cn.rulian.base.common.util.xx;
import cn.rulian.base.common.vo.Result;
import cn.rulian.demo.hello.bo.*;
import cn.rulian.tempcode.hello.dao.FullDaoTemp;
import cn.rulian.tempcode.hello.vo.FullFooter;
import cn.rulian.tempcode.hello.vo.FullVo;

/**
 * 全功能例子Service
 */
@Service
@Transactional(readOnly = true)
public class FullServiceTemp extends BaseService<Full>
{

	// private final Logger log = LoggerFactory.getLogger(getClass());

	@Autowired
	EntityManager em;

	@Autowired
	private FullDaoTemp dao;

	@Override
	protected FullDaoTemp getDao()
	{
		return dao;
	}
		
	/**
	 * 查询
	 */
	public Result query(final FullVo vo)
	{
		Sort sort = new Sort("desc".equals(vo.getOrder())?Direction.DESC:Direction.ASC, vo.getSort()); // 排序
		Pageable pageable = new PageRequest(vo.getPage() - 1, vo.getRows(), sort); // 分页查询条件

		//动态查询对象
		Specification<Full> specification = new Specification<Full>()
		{
			@Override
			public Predicate toPredicate(Root<Full> root, CriteriaQuery<?> cq, CriteriaBuilder cb)
			{
				return buildPredicate(root, cb, vo);
			}
		};

		// 查询
		Page<Full> page = dao.findAll(specification, pageable);
		Result result = Result.getResult(page);


		//构建合计项
		List<FullFooter> footer = new ArrayList<>();
		//(1)标题
		FullFooter title = new FullFooter();

		title.setIntNum1("整数");
		title.setIntNum2("整数2");
		title.setDoubleNum1("实数");
		title.setDoubleNum2("实数2");
		
		footer.add(title);

		//(2)本页合计
		List<Full> ls = page.getContent();
		footer.add(this.getOnePageSum(ls));
		
		//(3)所有符合条件的合计项
		footer.add(this.getAllSum(vo));
		result.setFooter(footer);
		return result;
	}
	

	/**
	 * 构建查询条件
	 */
	private Predicate buildPredicate(Root<Full> root, CriteriaBuilder cb, FullVo vo)
	{
		List<Predicate> predicates = new ArrayList<Predicate>();


		//编号
		String code = vo.getCode();
		if(!xx.isEmpty(code))
		{
			predicates.add(cb.like(root.get(Full_.code), "%" + code + "%"));
		}


		//名称
		String name = vo.getName();
		if(!xx.isEmpty(name))
		{
			predicates.add(cb.like(root.get(Full_.name), "%" + name + "%"));
		}


		//城市
		String city = vo.getCity();
		if(!xx.isEmpty(city))
		{
			predicates.add(cb.like(root.get(Full_.city), "%" + city + "%"));
		}

	
		// Full分类 ID
		String fullSortId = vo.getFullSortId();	
		if(!xx.isEmpty(fullSortId))
		{
			long num = xx.toLong(fullSortId);
			predicates.add(cb.equal(root.get(Full_.fullSort).get(FullSort_.id), num));
		}

	
		// 我的分类 ID
		String mySortId = vo.getMySortId();	
		if(!xx.isEmpty(mySortId))
		{
			long num = xx.toLong(mySortId);
			predicates.add(cb.equal(root.get(Full_.mySort).get(MySort_.id), num));
		}


		return cb.and(predicates.toArray(new Predicate[predicates.size()]));
	}


	/**
	 * 汇总一页数据的合计信息
	 * @param ls
	 * @return
	 */
	private FullFooter getOnePageSum(List<Full> ls)
	{
		FullFooter onePageSum = new FullFooter();

		long intNum1 = 0; // 整数
			
		long intNum2 = 0; // 整数2
			
		double doubleNum1 = 0; // 实数
		double doubleNum2 = 0; // 实数2
		
		for(Full bo:ls)
		{
			if(bo.getIntNum1()!=null)
			{
				intNum1 += bo.getIntNum1();
			}
			if(bo.getIntNum2()!=null)
			{
				intNum2 += bo.getIntNum2();
			}
			if(bo.getDoubleNum1()!=null)
			{
				doubleNum1 = Num.add(doubleNum1, bo.getDoubleNum1());
			}
			if(bo.getDoubleNum2()!=null)
			{
				doubleNum2 = Num.add(doubleNum2, bo.getDoubleNum2());
			}
			
		}

		onePageSum.setIntNum1(intNum1 + "");
		onePageSum.setIntNum2(intNum2 + "");
		onePageSum.setDoubleNum1(Num.format(doubleNum1));
		onePageSum.setDoubleNum2(Num.format(doubleNum2));

		onePageSum.setHobby("本页合计");
		//onePageSum.setHobby("本页合计");
		
		return onePageSum;
	}

	/**
	 * 获取所有符合条件的数据合计
	 */
	private FullFooter getAllSum(FullVo vo)
	{
		CriteriaBuilder cb = em.getCriteriaBuilder();
		CriteriaQuery<Tuple> cq = cb.createTupleQuery();

		// from
		Root<Full> root = cq.from(Full.class);

		// where
		cq.where(this.buildPredicate(root, cb, vo));

		// 合计项
		cq.multiselect(
				cb.sum(root.<Long> get("intNum1")).alias("intNum1")
				,cb.sum(root.<Long> get("intNum2")).alias("intNum2")
				,cb.sum(root.<Double> get("doubleNum1")).alias("doubleNum1")
				,cb.sum(root.<Double> get("doubleNum2")).alias("doubleNum2")
				);
		
		// 查询
		List<Tuple> rows = em.createQuery(cq).getResultList();
		Tuple tuple = rows.get(0);
		FullFooter all = new FullFooter();


		Long intNum1 = tuple.get("intNum1", Long.class); // 整数1
		all.setIntNum1(intNum1==null ? "0" : intNum1.toString());


		Long intNum2 = tuple.get("intNum2", Long.class); // 整数1
		all.setIntNum2(intNum2==null ? "0" : intNum2.toString());


		Double doubleNum1 = tuple.get("doubleNum1", Double.class); // 实数2
		all.setDoubleNum1(doubleNum1==null ? "0" : Num.format(doubleNum1));


		Double doubleNum2 = tuple.get("doubleNum2", Double.class); // 实数2
		all.setDoubleNum2(doubleNum2==null ? "0" : Num.format(doubleNum2));


		all.setHobby("总合计");

		return all;
	}

	
	/**
	 * 查询 Excel数据（不分页）
	 */
	public List<Full> QueryExcelData(final FullVo vo)
	{
		Sort sort = new Sort("desc".equals(vo.getOrder())?Direction.DESC:Direction.ASC, vo.getSort()); // 排序
		//动态查询对象
		Specification<Full> specification = new Specification<Full>()
		{
			@Override
			public Predicate toPredicate(Root<Full> root, CriteriaQuery<?> cq, CriteriaBuilder cb)
			{
				return buildPredicate(root, cb, vo);
			}
		};

		// 查询
		List<Full> list = dao.findAll(specification, sort);
		return list;
	}


}
